package graph.dependencies;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import tasks.ImplementTask;
import tasks.TaskPool;

public class ImplementableInterfaceDependency implements IDependency {
	private static List<TypeDeclaration> _classes = new LinkedList<TypeDeclaration>();
	
	private TypeDeclaration _interface = null;
	
	private List<TypeDeclaration> _implementList = new LinkedList<TypeDeclaration>(); 
	
	public ImplementableInterfaceDependency(TypeDeclaration node) {
		_interface=node;
	}

	@Override
	public boolean isLegal() {
		_implementList.clear();
		for (TypeDeclaration classDeclaration : _classes) {
			boolean alreadyImplemented = false;
			for (Object interf: classDeclaration.superInterfaceTypes()) {
				ITypeBinding superInterface = ((Type)interf).resolveBinding();
				if (superInterface.isEqualTo(_interface.resolveBinding())) {
					alreadyImplemented = true;
					/*System.out.println("ALREADY IMPLEMENTED "+_interface+" IN "+classDeclaration);*/
				}
			}
			if (!alreadyImplemented) {
				/*System.out.print("AMONG ");
				for (Object interf: classDeclaration.superInterfaceTypes())
					System.out.print(((Type)interf).resolveBinding()+"; ");
				System.out.println(" THERE IS NO "+_interface);*/
				int interfaceMethodsAreImplementable = 0;
				for (MethodDeclaration interfaceMethod : _interface.getMethods())
					for (MethodDeclaration classMethod : classDeclaration.getMethods())
						if (Bindings.isSubsignature(classMethod.resolveBinding(), interfaceMethod.resolveBinding())) {
							interfaceMethodsAreImplementable++;
							break;
						}
				if (interfaceMethodsAreImplementable==_interface.getMethods().length) {
					//System.out.println("CLASS "+classDeclaration+" SHOULD IMPLEMENT "+_interface);
					_implementList.add(classDeclaration);
				}
			}
		}
		if (_implementList.isEmpty())
			return true;
		return false;
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return "";
	}

	@Override
	public void scheduleFixTask() {
		if (isLegal())
			return;
		for (TypeDeclaration classForImplementTask : _implementList)
			TaskPool.getInstance().add(new ImplementTask(_interface,classForImplementTask));
	}

	
	public static void addClass(TypeDeclaration node) {
		for (Iterator<TypeDeclaration> i = _classes.iterator(); i.hasNext();) {
			TypeDeclaration alreadyAdded = i.next();
			if (alreadyAdded.resolveBinding().isEqualTo(node.resolveBinding()))
				i.remove();
		}
		_classes.add(node);
	}

	public static void clearClasses() {
		_classes.clear();		
	}

}
